/*
 * productorConsumidor.c
 *
 *  Created on: 11/11/2011
 *      Author: utn_so
 */
#include <stdio.h>
#include <stdlib.h>
#include "cola.h"
#include "tiposPlanificador.h"
#include <semaphore.h>
#include <errno.h>
#include "operacionesSectores.h"
#include <stdint.h>

void productorPedidos(void *arg) {
	PEDIDO *pedidoNuevo;
	struct datosPlanif *datosPlanificacion = (struct datosPlanif*) arg;
	printf("Soy el productor.\n");
	while (1) {
		pedidoNuevo = producirPedido(datosPlanificacion); //obtiene un pedido, le tengo q pasar parametros de socket para obtenerlo.
		if (datosPlanificacion->configuracion.algoPlanif == FSCAN) {
			if ((sem_trywait(datosPlanificacion->mutexFscanColas) == -1)
					&& (errno == EAGAIN)) {
				cola_listaInsertaNodo(datosPlanificacion->pedidosProximos,
						pedidoNuevo, ASCEN_PEDIDO);
			} else {
				cola_listaInsertaNodo(datosPlanificacion->pedidos, pedidoNuevo,
						ASCEN_PEDIDO);
			}
		} else {
			cola_listaInsertaNodo(datosPlanificacion->pedidos, pedidoNuevo,
					ASCEN_PEDIDO);

		}
		sem_post(datosPlanificacion->pedidosDisponibles);
	}
}
void consumidorPedidos(void *arg) {
	PEDIDO *pedidoAConsumir;
	struct datosPlanif *datosPlanificacion = (struct datosPlanif*) arg;
	printf("Soy el consumidor.\n");
	while (1) {
		if (datosPlanificacion->configuracion.algoPlanif == FSCAN) {
			if ((sem_trywait(datosPlanificacion->pedidosDisponibles) == -1)
					&& (errno == EAGAIN)) { //SI NO HAY MAS PEDIDOS INTERCAMBIO LAS COLAS
				cola_NODO* auxiliar = datosPlanificacion->pedidos;
				datosPlanificacion->pedidos =
						datosPlanificacion->pedidosProximos;
				datosPlanificacion->pedidosProximos = auxiliar;
				sem_post(datosPlanificacion->mutexFscanColas);
			}
		}
		sem_wait(datosPlanificacion->pedidosDisponibles);

		if (datosPlanificacion->configuracion.algoPlanif == FSCAN) {
			pedidoAConsumir = proximoPedidoFSCAN(datosPlanificacion);
		} else {
			pedidoAConsumir = proximoPedidoSCAN(datosPlanificacion);
		}
		consumirPedido(pedidoAConsumir, datosPlanificacion); //atiende el pedido y envia al que lo pidio

	}

}

PEDIDO *producirPedido(struct datosPlanif *datosPlanificacion) {
	//pedir un PEDIDO al RAID o el filesystem
	PEDIDO* pedidoProducido;
	pedidoProducido = desSerializarPedido(obtenerStream(datosPlanificacion));
	return pedidoProducido;
}
void consumirPedido(PEDIDO *pedido, struct datosPlanif *datosPlanificacion) {
	//Leo el sector y lo devuelvo por red.
	char* contenedorDeSector;
	contenedorDeSector = leerSector(pedido->sectorLogicoDestino,
			datosPlanificacion->regionDeMemoria);
	devolverStream(serializarContenedor(contenedorDeSector),
			datosPlanificacion);
}
PEDIDO *proximoPedidoFSCAN(struct datosPlanif *datosPlanificacion) {
	PEDIDO* proximoPedido;
	return proximoPedido;

}
PEDIDO *proximoPedidoSCAN(struct datosPlanif *datosPlanificacion) {
	PEDIDO* proximoPedido;
	cola_NODO *colaPista;
	cola_NODO *nodoTrabajo;
	PEDIDO *pedidoActual;
	do {
		for (nodoTrabajo = datosPlanificacion->pedidos; nodoTrabajo == NULL;
				nodoTrabajo = nodoTrabajo->siguiente) {
			pedidoActual=(PEDIDO*)nodoTrabajo->dato;
			if (pedidoActual->cilindro == datosPlanificacion->pistaActual) {
				cola_listaInsertaNodo(colaPista, pedidoActual, ASCEN_PEDIDO);
			}
		}
		if (colaPista == NULL) {//Si en la pista actual no hay pedidos
			if ((datosPlanificacion->pistaActual
					< datosPlanificacion->configuracion.c)
					&& (datosPlanificacion->orientacionCabeza == SUBIENDO)) {
				datosPlanificacion->pistaActual++;
			}
			if ((datosPlanificacion->pistaActual
					== datosPlanificacion->configuracion.c)
					&& (datosPlanificacion->orientacionCabeza == SUBIENDO)) {
				datosPlanificacion->orientacionCabeza = BAJANDO;
				datosPlanificacion->pistaActual--;
			}
			if ((datosPlanificacion->pistaActual > 0)
					&& (datosPlanificacion->orientacionCabeza == BAJANDO)) {
				datosPlanificacion->pistaActual--;
			}
			if ((datosPlanificacion->pistaActual == 0)
					&& (datosPlanificacion->orientacionCabeza == BAJANDO)) {
				datosPlanificacion->orientacionCabeza = SUBIENDO;
				datosPlanificacion->pistaActual++;
			}
		}
	} while (colaPista == NULL);

	proximoPedido = (PEDIDO*) colaPista->dato;

	return proximoPedido;

}
PEDIDO *desSerializarPedido(uint8_t* stream) {

}
uint8_t *serializarContenedor(char* pedido) {

}
void devolverStream(uint8_t* stream, struct datosPlanif *datosPlanificacion) {

}
uint8_t* obtenerStream(struct datosPlanif *datosPlanificacion) {

}
